#region Copyright (c) 2006-2009 Widgetsphere LLC, All Rights Reserved
//--------------------------------------------------------------------- *
//                          Widgetsphere  LLC                           *
//             Copyright (c) 2006-2009 All Rights reserved              *
//                                                                      *
//                                                                      *
//This file and its contents are protected by United States and         *
//International copyright laws.  Unauthorized reproduction and/or       *
//distribution of all or any portion of the code contained herein       *
//is strictly prohibited and will result in severe civil and criminal   *
//penalties.  Any violations of this copyright will be prosecuted       *
//to the fullest extent possible under law.                             *
//                                                                      *
//THE SOURCE CODE CONTAINED HEREIN AND IN RELATED FILES IS PROVIDED     *
//TO THE REGISTERED DEVELOPER FOR THE PURPOSES OF EDUCATION AND         *
//TROUBLESHOOTING. UNDER NO CIRCUMSTANCES MAY ANY PORTION OF THE SOURCE *
//CODE BE DISTRIBUTED, DISCLOSED OR OTHERWISE MADE AVAILABLE TO ANY     *
//THIRD PARTY WITHOUT THE EXPRESS WRITTEN CONSENT OF WIDGETSPHERE LLC   *
//                                                                      *
//UNDER NO CIRCUMSTANCES MAY THE SOURCE CODE BE USED IN WHOLE OR IN     *
//PART, AS THE BASIS FOR CREATING A PRODUCT THAT PROVIDES THE SAME, OR  *
//SUBSTANTIALLY THE SAME, FUNCTIONALITY AS ANY WIDGETSPHERE PRODUCT.    *
//                                                                      *
//THE REGISTERED DEVELOPER ACKNOWLEDGES THAT THIS SOURCE CODE           *
//CONTAINS VALUABLE AND PROPRIETARY TRADE SECRETS OF WIDGETSPHERE,      *
//INC.  THE REGISTERED DEVELOPER AGREES TO EXPEND EVERY EFFORT TO       *
//INSURE ITS CONFIDENTIALITY.                                           *
//                                                                      *
//THE END USER LICENSE AGREEMENT (EULA) ACCOMPANYING THE PRODUCT        *
//PERMITS THE REGISTERED DEVELOPER TO REDISTRIBUTE THE PRODUCT IN       *
//EXECUTABLE FORM ONLY IN SUPPORT OF APPLICATIONS WRITTEN USING         *
//THE PRODUCT.  IT DOES NOT PROVIDE ANY RIGHTS REGARDING THE            *
//SOURCE CODE CONTAINED HEREIN.                                         *
//                                                                      *
//THIS COPYRIGHT NOTICE MAY NOT BE REMOVED FROM THIS FILE.              *
//--------------------------------------------------------------------- *
#endregion
using System;
using System.ComponentModel;
using System.Xml;
using System.Collections;
using Widgetsphere.Generator.Common.GeneratorFramework;
using Widgetsphere.Generator.Common.Util;
using System.Collections.Generic;

namespace Widgetsphere.Generator.Models
{
	[
	Editor(typeof(Widgetsphere.Generator.Design.Editors.ReferenceCollectionEditor), typeof(System.Drawing.Design.UITypeEditor))
	]
  public class ReferenceCollection : BaseModelCollection
	{
		#region Member Variables
		
		protected List<Reference> _references = null;
		protected string _objectSingular = "Reference";
		protected string _objectPlural = "References";
		protected int _imageIndex = -1;
		protected int _selectedImageIndex = -1;
		protected IModelObject _parent = null;
		protected int lastId = 1;
		protected ReferenceType _refType = ReferenceType.Table;

		#endregion

		#region Constructor

    public ReferenceCollection(IModelObject root)
      : base(root)
		{
			_references = new List<Reference>();
		}

    public ReferenceCollection(IModelObject root, IModelObject parent, ReferenceType refType)
      : this(root)
		{
      _parent = parent;
			_refType = refType;
		}

		#endregion

		#region Property Implementations

		[Browsable(false)]
		public IModelObject Parent
		{
			get { return _parent; }
		}

		[Browsable(false)]
		public ReferenceType RefType
		{
			get { return _refType; }
		}

		[Browsable(false)]
		public string ObjectSingular
		{
			get { return _objectSingular; }
			set { _objectSingular = value; }
		}

		[Browsable(false)]
		public string ObjectPlural
		{
			get { return _objectPlural; }
			set { _objectPlural = value; }
		}		

		[Browsable(false)]
		public int ImageIndex
		{
			get { return _imageIndex; }
			set { _imageIndex = value; }
		}		

		[Browsable(false)]
		public int SelectedImageIndex
		{
			get { return _selectedImageIndex; }
			set { _selectedImageIndex = value; }
		}		

		#endregion

		#region Methods

		public Reference[] GetById(int id)
		{
			ArrayList retval = new ArrayList();
			foreach(Reference element in this)
			{
				if (element.Ref == id)
					retval.Add(element);
			}
			return (Reference[])retval.ToArray(typeof(Reference));
		}

    public Reference GetByKey(string key)
    {
      foreach (Reference element in this)
      {
        if (StringHelper.Match(element.Key, key, true))
          return element;
      }
      return null;
    }

    public Array FindReferencedObject(string key)
    {
      ArrayList retval = new ArrayList();
      foreach (IModelObject element in this)
      {
        if (StringHelper.Match(((Reference)element).Object.Key, key, true))
          retval.Add(element);
      }
      return retval.ToArray();
    }

		#endregion

		#region IXMLable Members

		public override void XmlAppend(XmlNode node)
    {
      try
      {
        XmlDocument oDoc = node.OwnerDocument;

        XmlAttribute keyNode = oDoc.CreateAttribute("key");
        keyNode.Value = this.Key.ToString();
        node.Attributes.Append(keyNode);

        foreach(Reference Reference in _references)
        {
          XmlNode ReferenceNode = oDoc.CreateElement("Reference");
          Reference.XmlAppend(ReferenceNode);
          node.AppendChild(ReferenceNode);
        }
      }
      catch(Exception ex)
      {
        throw;
      }

    }

		public override void XmlLoad(XmlNode node)
		{
      try
      {
        _key = XmlHelper.GetAttributeValue(node, "key", _key);
        XmlNodeList referenceNodes = node.SelectNodes("Reference");
        foreach(XmlNode referenceNode in referenceNodes)
        {
          Reference newReference = new Reference(this.Root);
          newReference.XmlLoad(referenceNode);
          _references.Add(newReference);
          if(lastId < newReference.Ref)
            lastId = newReference.Ref;
        }

        this.Dirty = false;
      }
      catch(Exception ex)
      {
        throw;
      }
		}

		#endregion

		#region IList Members

		//[Browsable(false)]
		//public bool IsReadOnly
		//{
		//  get { return _references.IsReadOnly; }
		//}

    public Reference this[int index]
    {
      get { return _references[index]; }
      //set { _references[index] = value; }
    }

		public Reference this[string name]
		{
			get
			{
				Reference retval = FindByName(name);
				if (retval == null)
					throw new Exception("Item not found!");
				else
					return retval;
			}
		}

		public Reference FindByName(string name)
		{
			foreach (Reference element in this)
			{
				switch (element.RefType)
				{
					case ReferenceType.Column:
						if (((Column)element.Object).Name == name)
							return element;
						break;
					case ReferenceType.Relation:
						if (((Relation)element.Object).ConstraintName == name)
							return element;
						break;
					case ReferenceType.Table:
						if (((Table)element.Object).Name == name)
							return element;
						break;
					case ReferenceType.CustomRetrieveRule:
						if (((CustomRetrieveRule)element.Object).Name == name)
							return element;
						break;
					case ReferenceType.Parameter:
						if (((Parameter)element.Object).Name == name)
							return element;
						break;
					case ReferenceType.CustomViewColumn:
						if (((CustomView)element.Object).Name == name)
							return element;
						break;
				}
			}
			return null;
		}

    public void RemoveAt(int index)
		{			
			_references.RemoveAt(index);			
		}

		public void Insert(int index, Reference value)
		{
			_references.Insert(index, value);
		}

		public void Remove(Reference value)
		{
			_references.Remove(value);
		}

		public void RemoveRange(IEnumerable range)
		{
			foreach(Reference element in range)
				this.Remove(element);
		}

		public bool Contains(Reference value)
		{
			return _references.Contains(value);
		}

		public bool Contains(int id)
		{
			foreach(Reference reference in this)
			{
				if (reference.Ref == id)
					return true;
			}
			return false;
		}

    public bool Contains(string key)
    {
      foreach (Reference reference in this)
      {
        if (reference.Key == key)
          return true;
				if (reference.Object.Key == key)
					return true;
      }
      return false;
    }

		public override void Clear()
		{
			//Clear each one-by-one
			for (int ii = this.Count - 1; ii >= 0; ii--)
			{
				this.RemoveAt(0);
			}
		}

		public int IndexOf(Reference value)
		{
			return _references.IndexOf(value);
		}

		internal void Add(Reference value)
		{
			_references.Add(value);
		}

    public override void AddRange(ICollection list)
    {
			foreach (Reference reference in list)
			{
				_references.Add(reference);
			}
    }

		public Reference Add()
		{
			Reference newItem = new Reference(this.Root);
			lastId++;
			newItem.Ref = lastId;
			this.Add(newItem);
			return newItem;
		}

		//[Browsable(false)]
		//public bool IsFixedSize
		//{
		//  get { return _references.IsFixedSize; }
		//}

		#endregion

		#region ICollection Members

		[Browsable(false)]
		public override bool IsSynchronized
		{
			get { return false; }
		}

		[Browsable(false)]
    public override int Count
		{
			get
			{
				return _references.Count;
			}
		}

    public override void CopyTo(Array array, int index)
		{
			_references.CopyTo((Reference[])array, index);
		}

		private object _syncRoot = "QQQ";

		[Browsable(false)]
		public override object SyncRoot
		{
			get { return _syncRoot; }
		}

		#endregion

		#region IEnumerable Members

		public override IEnumerator GetEnumerator()
		{
			return _references.GetEnumerator();
		}

		#endregion

  }
}
